package com.etop.ondoc.dao;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.annotation.Resource;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;

import com.etop.ondoc.util.Pager;
import com.etop.ondoc.util.SystemContext;

public class BaseDao<T> implements IBaseDao<T>{
	
	@Resource(name="sessionFactory")
	private SessionFactory sessionFactory;
	
	protected Session getSession(){
		return sessionFactory.getCurrentSession();
	}
	/**
	 * 创建一个Class的对象来获取泛型的class
	 */
	private Class<T> clz;
	
	@SuppressWarnings("unchecked")
	public Class<T> getClz() {
		if(clz==null) {
			//获取泛型的Class对象
			clz = ((Class<T>)
					(((ParameterizedType)(this.getClass()
						.getGenericSuperclass()))
							.getActualTypeArguments()[0]));
		}
		return clz;
	}

	@Override
	public void add(T t) {
		this.getSession().save(t);
	}
	@Override
	public void delete(int id) {
		this.getSession().delete(this.load(id));
	}
	@Override
	public void update(T t) {
		this.getSession().update(t);
	}
	@Override
	public T load(int id) {
		return (T) this.getSession().load(getClz(),id);
	}
	
	public List list(String hql, Object[] args) {
		Query q = this.getSession().getSessionFactory().getCurrentSession().createQuery(hql);
		if(args!=null){
			for(int i=0;i<args.length;i++){
				q.setParameter(i, args[i]);
			}
		}
		List<T> list = q.list();
		return list;
	}

	@Override
	public List<T> list(String hql) {
		return this.list(hql, null);
	}

	@Override
	public List<T> list(String hql, Object args) {
		return this.list(hql, new Object[]{args});
	}
	public int count(DetachedCriteria dc){
        Criteria c = dc.getExecutableCriteria(
                this.getSession()
            ).setProjection(
                Projections.rowCount()
            );

        return((int)c.uniqueResult());
    }
	public List search(DetachedCriteria dc,Integer pageSize,Integer pageOffset,String order,String sort){
		
		Criteria c = dc.getExecutableCriteria(getSession());
		if ("asc".equals(order))
			c.addOrder(Order.asc(sort));
		if ("desc".equals(order))
			c.addOrder(Order.desc(sort));
		if(pageOffset!=null)
			c.setFirstResult(pageOffset);
		if(pageSize!=null)
			c.setMaxResults(pageSize);
		return (c.list());
	}
	public Pager<T> find() {
		DetachedCriteria dc = DetachedCriteria.forClass(getClz());
		Integer pageSize = SystemContext.getPageSize();
		Integer pageOffset = SystemContext.getPageOffset();
		String order = SystemContext.getOrder();
		String sort = SystemContext.getSort();
		Pager<T> pages = new Pager<T>();
		Session session = null;
		try{
			session = this.getSession();
			List<T> datas = this.search(dc, pageSize, pageOffset, order, sort);
			pages.setDatas(datas);
			pages.setPageOffset(pageOffset);
			pages.setPageSize(pageSize);
			int totalRecord = this.count(dc);
			pages.setTotalRecord(totalRecord);
		} catch(Exception e){
		}
		return pages;
	}
	
}
